/*
 Copyright (c) 2020-2023 Xiamen Yaji Software Co., Ltd.

 https://www.cocos.com/

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights to
 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 of the Software, and to permit persons to whom the Software is furnished to do so,
 subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
*/

import { _decorator, Component, Node, SkeletalAnimation, ParticleSystem, Vec3, utils } from 'cc';
import { ActorAnimationGraph } from './actor-animation-graph';
import { ActionActor, key_type_boolean } from '../action/action';
import { Msg } from '../../util/msg';
import { ResCache } from '../res/res-cache';
import { Util, UtilNode, UtilVec3 } from '../../util/util';
import { ResPool } from '../res/res-pool';
const { ccclass } = _decorator;

export type KeyAnyType = {
    [key:string]:any;
}


@ccclass('ActorBase')
export class ActorBase extends Component {

    // _action是角色的动作控制器
    _action: ActionActor | undefined;
    _data: KeyAnyType = {};
    _updates: Function[] = [];

    //是否禁止移动
    _isDisableStop = false;

    _dir = new Vec3(0, 0, 0);
    _curDir = new Vec3(0, 0, 0);

    _angleVertical = 0;
    _groupIndex = -1;

    //角色的逻辑坐标
    _logicPos = new Vec3(0, 0, 0);
    //角色的显示坐标
    _showPos = new Vec3(0, 0, 0);

    isPlayer = false;

    _anim: SkeletalAnimation | undefined;
    _animationGraph: ActorAnimationGraph | undefined;

    // _view是角色的模型节点，用于播放动画
    _view: Node | undefined;

    // viewPointHead是角色的头部节点，用于计算角色的朝向
    viewPointHead: Node | undefined | null;

    _actionUpdate = () => { };

    __preload (): void {
        this.onBind();
    }

    init (dataJsonName: string) {

        // 从缓存中获取角色的配置数据
        this._data = Util.deepCopy(ResCache.Instance.getJson(dataJsonName).json);

        if (this._action == undefined) this._action = new ActionActor(this._data.action, this);
        //找到角色的模型节点
        if (this._view == undefined) this._view = UtilNode.find(this.node, 'view');
        //找到角色的头部节点
        if (this.viewPointHead == undefined) this.viewPointHead = UtilNode.find(this.node, 'view_point_head');

        //找到角色的动画组件
        this.initView();

        this.node.on('input_swipe_left', this.moveToLeft, this);
        this.node.on('input_swipe_right', this.moveToRight, this);
        this.node.on('input_swipe_up', this.moveToUp, this);
        this.node.on('input_swipe_down', this.moveToDown, this);
    }

    initView () { }

    //onBind是绑定事件  
    onBind () {
        //this.node.on是cocos的事件绑定函数，用来绑定事件，用法是this.node.on(事件名，回调函数，回调函数的作用域)
        //如何触发this.node.on绑定的事件，可以用this.node.emit(事件名，参数1，参数2，参数3，参数4，参数5)
        this.node.on('do', this.do, this);
        this.node.on('onGround', this.onGround, this);
        this.node.on('offGround', this.offGround, this);
        this.node.on('moveToSky', this.moveToSky, this);
        //guide_end是
        Msg.on('guide_end', this.onGuideEnd.bind(this));
    }

    offBind () {
        this.node.off('do', this.do, this);
        this.node.off('onGround', this.onGround, this);
        this.node.off('offGround', this.offGround, this);
        this.node.off('moveToSky', this.moveToSky, this);
        Msg.on('guide_end', this.onGuideEnd.bind(this));
    }

    moveToLeft(){
      
    }

    moveToRight(){
   
    }

    moveToUp(){
     
    }

    moveToDown(){
     
    }

    //onGuideEnd是引导结束的回调函数
    onGuideEnd () {
        this.do('play');
    }

    moveToSky () {
        if (this._data.is_jump) return;
        this.do('move_to_sky');
    }

    onGround () {
        if (this._data.is_jump) this.do('jump_to_ground');
        this.do('on_ground');
    }

    offGround () {
        this.do('off_ground');
    }

    onUpdate () { }

    offUpdate () {
        this._updates = [];
    }

    updateAttribute () { }

    onDestroy () {
        this.offBind();
    }

    do (name: string) {
        if (this._action) this._action.on(name);
    }

    //update是角色的更新函数，deltaTime是每帧的时间间隔
    update (deltaTime: number) {
        if (this._action) this._action.update(deltaTime);
        var count = this._updates.length;
        for (let i = 0; i < count; i++)
            this._updates[i](deltaTime);

        if (this._data.jumping && this._data.is_ground) {
            this.do('jump_to_ground');
        }

    }


    setActive (data: key_type_boolean) {
        //this.node.getChildByName(data.key)是获取当前节点下的子节点，data.key是子节点的名字
        const activeNode = this.node.getChildByName(data.key);
        //如果子节点存在，就设置子节点的active属性  
        if (activeNode) activeNode.active = data.value;
        //如果子节点不存在，就打印警告      
        else console.warn(` You want set undefined node active. ${this.node?.name}/${data.key}`);
    }

    //setFx是设置粒子效果的函数
    setFx (data: key_type_boolean) {
        const pNode = UtilNode.find(this.node, data.key);//this.node.getChildByName(data.key);
        const particles = pNode?.getComponentsInChildren(ParticleSystem);
        if (particles === undefined) return;
        for (let i = 0; i < particles.length; i++) {
            let p = particles[i];
            p.loop = data.value;
            if (data.value) p.play();
        }
    }

    //  playFx是播放粒子效果的函数
    onFx (data: string) {
        const pNode = UtilNode.find(this.node, data);//this.node.getChildByName(data);
        const particles = pNode?.getComponentsInChildren(ParticleSystem);
        if (particles === undefined) return;
        for (let i = 0; i < particles.length; i++) {
            let p = particles[i];
            p.play();
        }
    }

    actionEnd () { }

    //setDir是设置角色的朝向的函数
    setDir (dir: Vec3) {
        UtilVec3.copy(this._dir, dir);
    }

    //updateHP是设置角色的生命值的函数
    updateHP () {
        const percent_hp = this._data.hp / this._data.max_hp;
        Msg.emit('fil_hp', percent_hp);
    }

    //onDead是角色死亡的回调函数    
    onDead () {

        if (!this.isPlayer) {
            if (this._groupIndex !== -1) {
                Msg.emit('msg_remove_level_enemy', this.node);
                Msg.emit('msg_remove_enemy', this._groupIndex);
                Msg.emit(
                    'msg_tips',
                    `killed_one`
                );
            }
            //this.node?.destroy();
            ResPool.Instance.push(this.node);
        }

    }

}